require('./app-config');
const ResultVo = appRequire('vo/ResultVo.js');
const SysUserService = appRequire('service/desktop/SysUserService.js');
const Koa = require('koa')
const cors = require('koa2-cors')
const app = new Koa()
app.use(cors())
const Router = require('koa-router')
const router = Router()
const views = require('koa-views')
const json = require('koa-json')
const onerror = require('koa-onerror')
// const bodyparser = require('koa-bodyparser')
const koaBody = require('koa-body');
const logger = require('koa-logger')
// 启用koa-session中间件
const session = require('koa-session');
app.keys = ['I am thgold'];
const CONFIG = {
  key: appConfig.session_id,   //cookie key (default is koa:sess)
  maxAge: 86400000,  // cookie的过期时间 maxAge in ms (default is 1 days)
  overwrite: true,  //是否可以overwrite    (默认default true)
  httpOnly: true, //cookie是否只有服务器端可以访问 httpOnly or not (default true)
  signed: true,   //签名默认true
  rolling: false,  //在每次请求时强行设置cookie，这将重置cookie过期时间（默认：false）
  renew: false,  //(boolean) renew session when session is nearly expired,
};
app.use(session(CONFIG, app));
// koa-static静态资源中间件的功能
const static = require('koa-static');
const { sequelize } = require('./model/desktop/SysUser');

// const index = require('./routes/index')
// const users = require('./routes/users')

// error handler
onerror(app)

// middlewares
// app.use(bodyparser({
//   enableTypes:['json', 'form', 'text']
// }))
app.use(koaBody());
app.use(json())
app.use(logger());

appConfig.allowedUrls = initAllowedUrls(appConfig.allowedUrls);
// console.log(appConfig.allowedUrls);
/**
 * 判断用户是否有静态资源授权或API授权
 */
async function isAuthorized(ctx) {
  let isAuthorized = false;
  //用户拥有的url权限
  let curUrl = ctx.url;
  let ses_user = ctx.session.user;
  let user = {};
  if (ses_user) {
    let mem_user =appConfig.db[ses_user.username];
    if(!mem_user){
      let data = await SysUserService.findUserAuthItem(ses_user.id);
      user.authUrls = data.authUrls;
      user.menuInfo = data.authMenus;
      appConfig.db[user.username] = user;
    }else{
      user = mem_user;
    }
    // console.log(user);
    if (user&&user.authUrls) {
      for (let i = 0; i < user.authUrls.length; i++) {
        console.log(user.authUrls[i]+","+curUrl);
        if (curUrl.match(user.authUrls[i])) {
          isAuthorized = true;
          break;
        }
      }
    }
  }
  console.log(curUrl+":isAuthorized:"+isAuthorized);
  return isAuthorized;
}

/**
 * 使用应用级中间件，保护静态资源;
 */

/**
 * 允许通过的url
 */
// let allowedUrl = [ 
//     //静态放行url
//     appConfig.authPrefixUrl + '/*',
//     '/favicon.ico',
//     '/dicms/static/desktop/data/public/*',
//     '/dicms/static/desktop/ui1/page/login.html',
//     '/dicms/static/desktop/ui1/page/404.html',
//     '/dicms/static/desktop/ui1/page/403.html',
//     '/dicms/static/desktop/ui1/my.html',
//     // '/dicms/desktop/ui1/index.html',
//     // todo bug 暴露权限
//     '/dicms/static/desktop/ui1/api/*',
//     '/dicms/static/desktop/ui1/css/*',
//     '/dicms/static/desktop/ui1/images/*',
//     '/dicms/static/desktop/ui1/js/*',
//     '/dicms/static/desktop/ui1/lib/*',
    
//     //API放行url
//     '/dicms/api/desktop/sys_user/login',
//     '/dicms/api/desktop/sys_user/logout',
//     // '/dicms/api/desktop/sys_auth/create',
// ];
/**
 * 拦截器，拦截需要拦截的请求
 */
app.use(async (ctx, next) => {
  let curUrl = ctx.url;
  console.log(curUrl);
  //静态资源授权校验,拦截受保护的静态资源,必须在静态路由前拦截，否则无法拦截,默认全部拦截
  let isAllowed = false;
   //读取配置的不拦截的静态url
   for (let i = 0; i < appConfig.allowedUrls.length; i++) {
    if (curUrl.match(appConfig.allowedUrls[i])) {
      isAllowed = true;
      break;
    }
  }
  let isAjax = false;
  let header = ctx.request.header;
  if(header['x-requested-with']&&header['x-requested-with']==='XMLHttpRequest'){
    isAjax = true;
  }
  //isAllowed为true，不拦截该静态资源，跳到静态路由处理。需要session验证用户静态权限的url
  if (!(isAllowed || await isAuthorized(ctx))) {
    console.log("isAllowed:"+isAllowed+",Authorized验证不通过!");
    if (curUrl.startsWith(appConfig.staticPrefixUrl)) {
      if(!isAjax){
        ctx.redirect('/dicms/static/desktop/ui1/page/404.html');
      }else{
        ctx.body={code:-1,msg:"您访问的页面不存在!"}
      }
      // API授权校验,读取配置的不拦截的API url
    }else if (curUrl.startsWith(appConfig.authPrefixUrl)){
      if(!isAjax){
        ctx.redirect('/dicms/static/desktop/ui1/page/403.html');
      }else{
        ctx.body={code:-1,msg:"您没有权限访问:"+curUrl}
      }
    }
    return;
  }
  console.log("isAllowed:"+isAllowed+",Authorized验证通过~~~");
  await next();
});
app.use(static(__dirname + '/public'))

app.use(views(__dirname + '/views', {
  extension: 'ejs'
}))

// logger
app.use(async (ctx, next) => {
  const start = new Date()
  await next()
  const ms = new Date() - start
  console.log(`${ctx.method} ${ctx.url} - ${ms}ms`)
})

// routes
// app.use(index.routes(), index.allowedMethods())
// app.use(users.routes(), users.allowedMethods())
/**
 * 使用require-dir中间件，动态引入controller
 */
let controllers = require('require-dir')(appConfig.controllerUrl, { recurse: true });
// console.log(controllers);
//设置所有路由的根路由
// router.prefix(appConfig.authPrefixUrl);
function loadControllers(controllers, rootPath) {
  Object.keys(controllers).map(function (v, i) {
    // console.log(typeof controllers[v]);
    if (typeof controllers[v] === 'object'&&!(controllers[v] instanceof Router)) {
      loadControllers(controllers[v], rootPath + v + '/');
    } else {
      if(controllers[v] instanceof Router){
        console.log(rootPath + v);
      // 按目录级别划分层级关系
      // router.use(rootPath+v,controllers[v]);
      // console.log(controllers[v]);
      router.use(controllers[v].routes(),controllers[v].allowedMethods());
      }
    }
  });
}
loadControllers(controllers, '/');
let routerConfig = router.stack;
let routerMappingList = routerConfig.map(function(val){
  return {moduleName:val.opts.prefix,path:val.path};
});
let routerMapping = {};
routerMappingList.forEach(function(val){
  if(val.moduleName!==''){
    if(!routerMapping[val.moduleName]){
      routerMapping[val.moduleName] = [];
    }else{
      routerMapping[val.moduleName].push(val.path);
    }
  }
});

console.log("routerMapping:"+routerMapping);
app.use(router.routes()); //作用：启动路由
app.use(router.allowedMethods()); // 作用： 这是官方文档的推荐用法,我们可以看到router.allowedMethods()用在了路由匹配router.routes()之后,所以在当所有路由中间件最后调用.此时根据ctx.status设置response响应头

// let User = appRequire("model/desktop/SysUser");
// (async function(){
//   console.log("........................");
//   await sequelize.sync();
//   const users = await User.findAll({raw: true,});
//   console.log(users);
// })();
// error-handling
app.on('error', (err, ctx) => {
  // console.error('server error', err, ctx)
  ctx.body = ResultVo.error(-1,err.msg,err.message);;
});

module.exports = app
